package yang.java8.streamAPI;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import yang.java8.util.MyObject;
import yang.java8.util.Util;

public class Practice2 {
	
	public static void main(String[] args) {
		test12();
//		StreamApi.limit_skip_concat_peek();
	}
	
	/**
	 * 找到5个之后就不会执行filter了
	 */
	public static void test2() {
		Stream<MyObject> stream = Util.generateMyObjectList(100).stream();
		stream.filter(v -> v.getIndex() > 0).limit(5).count();
	}
	
	public static void test5() {
		Stream<Long> stream = Stream.iterate(0L, v -> (25214903917L * v + 11) % (2<<48));
		stream.peek(System.out::println).limit(10).count();
	}
	
	public static void test6() {
		String s = "abcd";
//		Stream<Character> stream = Stream.iterate(0, v -> v + 1).map(v -> s.charAt(v)).limit(s.length());
//		Util.showStream(stream, 10);
		
		IntStream intStream = IntStream.range(0, s.length());
		Stream<Character> stream = intStream.mapToObj(s::charAt);
		stream.forEach(System.out::println);
	}
	
	/**
	 * 判断一个流是不是无线的，不是个好主意
	 */
	public static void test7() {
		Stream<String> stream = Stream.iterate("", String::toString);
//		Iterator<String> i = stream.iterator();
		System.out.println(Stream.of(1).spliterator().estimateSize());
		System.out.println(stream.spliterator().estimateSize());
		System.out.println(Long.MAX_VALUE);
		// limit貌似不参与size
		System.out.println(Stream.of(1,2,3).limit(1).spliterator().estimateSize());
		System.out.println(Stream.iterate(1, x -> x).limit(1).spliterator().estimateSize());

	}
	
	public static void test8() {
//		Stream<String> first = Stream.of("f,i,r,s,t".split(","));
//		Stream<String> second = Stream.of("s,e,c,o,n,d".split(","));
		// 注意，无线流则会导致无线循环
		Stream<String> first = Stream.iterate("0", v -> v + "0");
		Stream<String> second = Stream.iterate("1", v -> v + "0");
		Iterator<String> firstIt = first.iterator();
		Iterator<String> secondIt = second.iterator();
		Iterator<String> it = new Iterator<String>() {
			
			private boolean isFirst = true;

			@Override
			public boolean hasNext() {
				return isFirst ? firstIt.hasNext() : secondIt.hasNext();
			}

			@Override
			public String next() {
				String ret = isFirst ? firstIt.next() : secondIt.next();
				isFirst = !isFirst;
				return ret;
			}
		};
		
		while (it.hasNext()) {
			System.out.println(it.next());
			
		}
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes", "unused" })
	public static void test9() {
		Stream<ArrayList<String>> stream = Stream.iterate(new ArrayList<>(), ArrayList<String>::new);
		ArrayList<String> ret = new ArrayList<>();
		stream.reduce((v1, v2) -> {
			v1.addAll(v2);
			return v1;
		});
		
		stream.reduce(new ArrayList(), (v1, v2) -> {
			v1.addAll(v2);
			return v1;
		});
		
		stream.reduce(new ArrayList(), (v1, v2) -> {
			v1.addAll(v2);
			return v1;
		}, (v1, v2) -> {
			v1.addAll(v2);
			return v1;
		});
	}
	
	public static void test10() {
		Stream<Double> stream = Stream.iterate(0.0, v -> v + 1.0).limit(10);
		AtomicInteger count = new AtomicInteger(0);
		Double totalAdd = stream.reduce(0., (total, num) -> {
			count.incrementAndGet();
            return total + num;
        });
		System.out.println(totalAdd / count.get());
		
	}
	
	public static void test11() {
		Stream<Integer> stream = Stream.iterate(0, v -> v + 1).limit(10);
		List<Integer> list = Util.generateIntList(10);
		stream.peek(v -> list.set(v, v)).forEach(System.out::println);
//		stream.forEach(System.out::println);
		list.stream().forEach(System.out::println);
	}
	

	public static void test12() {
		Stream<MyObject> stream = Util.generateMyObjectList(100).stream();
		AtomicInteger[] arr = Util.generateAtomicIntList(100, 0);
		stream.parallel().forEach(v -> {
			if (v.getValue().length() < 100) {
				arr[v.getValue().length()].incrementAndGet();
			}
		});
		Stream.of(arr).forEach(System.out::println);
	}

	
	public static void test13() {
		Stream<MyObject> stream = Util.generateMyObjectList(100).stream();
		stream.collect(Collectors.groupingBy(MyObject::getValue, Collectors.mapping(MyObject::getValue, Collectors.joining())));
	}


}
